package com.ttxs.generator.engine;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.AbstractTemplateEngine;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.ttxs.generator.output.Output;
import com.ttxs.generator.util.Constants;
import com.ttxs.generator.util.DirectoryUtils;
import com.ttxs.generator.util.PathUtils;
import com.ttxs.generator.vo.FormBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static com.ttxs.generator.util.TableInfoUtils.isCompositeKey;

@Slf4j
@Component
public class CustomFreemarker extends FreemarkerTemplateEngine {
    @Autowired
    private List<Output> outputList;
    @Autowired
    private List<Output> staticRouteOutputList;

    @Override
    public AbstractTemplateEngine batchOutput() {
        try {
            // 复制前端参考项目
            copyVueProject();
            // 按表名循环输出文件
            super.batchOutput();
            // 添加包配置信息到自定义输出文件需要的map
            customMap().put("package", getConfigBuilder().getPackageConfig().getPackageInfo());
            // 创建子模块标志
            customMap().put("hasModule", hasModule());
            if (hasModule()) {
                customMap().put("customParentPackage", getCustomParentPackage());
                customMap().put("customParentPath", getCustomParentPath());
            }
            // 输出单个文件
            for (Output customOutput : outputList) {
                customOutput.write(this);
            }
            // 输出单个静态路由文件
            if(formBean().isStaticRoute()) {
                for (Output output : staticRouteOutputList) {
                    output.write(this);
                }
            }
            // 自动创建平台、用户、菜单并授权
            if(!formBean().isStaticRoute()) {
                new AutoCreatePlatform(formBean(), getConfigBuilder().getTableInfoList())
                    .autoCreate();
            }
        } catch (IOException e) {
            throw new RuntimeException("无法创建前端文件，请检查配置信息！", e);
        }
        return this;
    }

    public boolean hasModule() {
        return StringUtils.hasText(formBean().getModuleName());
    }
    /**
     * 去除模块名的项目父绝对路径
     * @return
     */
    public String getCustomParentPath() {
        return getConfigBuilder().getGlobalConfig().getOutputDir()
                + File.separator + getCustomParentPackage().replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
    }

    /**
     * 去除模块名的项目父包名
     * @return
     */
    public String getCustomParentPackage() {
        String parent = getConfigBuilder().getPackageConfig().getParent();
        return parent.substring(0, parent.lastIndexOf(StringPool.DOT));
    }

    /**
     * 项目父绝对路径
     * @return
     */
    public String getParentPath() {
        return getConfigBuilder().getGlobalConfig().getOutputDir()
                + File.separator + getParentPackage().replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
    }
    /**
     * 项目父包名
     * @return
     */
    public String getParentPackage() {
        return getConfigBuilder().getPackageConfig().getParent();
    }

    /**
     * 根据表信息输出js和vue文件，模板自动调用，请勿直接调用
     * js输出路径为：    src/api/${projectName}/${entityName}/index.js
     * vue页面输出路径为：src/views/${projectName}/${entityName}/index.vue
     * 注意：没有主键的表或复合主键的表不会生成文件
     *
     * @param customFile
     * @param tableInfo
     * @param objectMap
     * @return
     */
    @Override
    protected void outputCustomFile(Map<String, String> customFile, TableInfo tableInfo, Map<String, Object> objectMap) {
        customFile.forEach((key, value) -> {
            if (tableInfo.isHavePrimaryKey() && !isCompositeKey(tableInfo)) {
                String fileName = getFileName(key, tableInfo);
                outputFile(new File(fileName), objectMap, value);
            } else {
                log.info("表{}没有主键或是复合主键，不生成.js和.vue文件", tableInfo.getName());
            }
        });
    }

    @Override
    public String getPathInfo(OutputFile outputFile) {
        return super.getPathInfo(outputFile);
    }

    @Override
    public void outputFile(File file, Map<String, Object> objectMap, String templatePath) {
        super.outputFile(file, objectMap, templatePath);
    }

    public FormBean formBean() {
        return (FormBean) this.getConfigBuilder().getInjectionConfig().getCustomMap().get(Constants.FORM_BEAN);
    }

    public Map<String, Object> customMap() {
        return this.getConfigBuilder().getInjectionConfig().getCustomMap();
    }

    private String getFileName(String key, TableInfo tableInfo) {
        String entityName = StringUtils.uncapitalize(tableInfo.getEntityName());
        String artifactId = formBean().getArtifactId();
        String apiJsPath = PathUtils.get(PathUtils.Vue.api, formBean().getVueProjectPath());
        String vuePagePath = PathUtils.get(PathUtils.Vue.views, formBean().getVueProjectPath());
        if(formBean().isSpringCloud()) {
            apiJsPath += File.separator + formBean().getPlatformName();
            vuePagePath += File.separator + formBean().getPlatformName();
        }
        String moduleName = formBean().getModuleName();
        // 判断生成vue页面还是js，返回不同的文件路径名字
        return ("index.js".equals(key) ? apiJsPath : vuePagePath) + File.separator
                + artifactId + File.separator
                + (hasModule() ? moduleName + File.separator : "")
                + entityName + File.separator + key;
    }

    private void copyVueProject() throws IOException {
        if(!StringUtils.hasText(formBean().getTtxsUiVuePath())) {
            return;
        }
        String source = formBean().isStaticRoute()
                ? formBean().getTtxsUiVuePath() + "2"
                : formBean().getTtxsUiVuePath();
        DirectoryUtils.copyDirectory(source, formBean().getVueProjectPath(), "node_modules");
    }

}
